package cn.com.taiji.pos.common.util;


import cn.com.taiji.pos.entity.*;
import cn.com.taiji.pos.service.ISystemProjectService;
import com.alibaba.fastjson.JSONObject;
import lombok.Setter;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class SmallTicketPrinter {

    @Value("${fei_Url}")
    private String URL;// 不需要修改
    @Value("${fei_User}")
    private String USER;// *必填*：账号名
    @Value("${fei_Ukey}")
    private String UKEY;// *必填*:// 飞鹅云后台注册账号后生成的UKEY
    @Value("${fei_SN}")
    public String SN;// *必填*：打印机编号，必须要在管理后台里添加打印机或调用API接口添加之后，才能调用API
    @Value("${PROJECT_CODE}")
    private String PROJECT_CODE;
    @Value("${memberCode}")
    private String memberCode;
    @Value("${apiKey}")
    private String apiKey;
    @Value("${templetID}")
    private String templetID;
    @Value("${table_printer_code}")
    private String tablePrinterCode;
    @Value("${print_quantity}")
    private String printQuantity;
    @Autowired
    private ISystemProjectService systemProjectService;
    //小票序号
    @Setter
    private AtomicInteger printSerialNumber = new AtomicInteger(1);


    // 生成签名字符串
    private static String signature(String USER, String UKEY, String STIME) {
        String s = DigestUtils.shaHex(USER + UKEY + STIME);
        return s;
    }


    public String print(String content, String sn) {
        // 标签说明：
        // 单标签:
        // "<BR>"为换行,"<CUT>"为切刀指令(主动切纸,仅限切刀打印机使用才有效果)
        // "<LOGO>"为打印LOGO指令(前提是预先在机器内置LOGO图片),"<PLUGIN>"为钱箱或者外置音响指令
        // 成对标签：
        // "<CB></CB>"为居中放大一倍,"<B></B>"为放大一倍,"<C></C>"为居中,<L></L>字体变高一倍
        // <W></W>字体变宽一倍,"<QR></QR>"为二维码,"<BOLD></BOLD>"为字体加粗,"<RIGHT></RIGHT>"为右对齐
        // 拼凑订单内容时可参考如下格式
        // 根据打印纸张的宽度，自行调整内容的格式，可参考下面的样例格式

        // 通过POST请求，发送打印信息到服务器
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)// 读取超时
                .setConnectTimeout(30000)// 连接超时
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig).build();
        System.err.println(URL);
        HttpPost post = new HttpPost(URL);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("user", USER));
        String STIME = String.valueOf(System.currentTimeMillis() / 1000);
        nvps.add(new BasicNameValuePair("stime", STIME));
        nvps.add(new BasicNameValuePair("sig", signature(USER, UKEY, STIME)));
        nvps.add(new BasicNameValuePair("apiname", "Open_printMsg"));// 固定值,不需要修改
        nvps.add(new BasicNameValuePair("sn", sn));
        nvps.add(new BasicNameValuePair("content", content));
        nvps.add(new BasicNameValuePair("times", printQuantity));// 打印联数

        CloseableHttpResponse response = null;
        String result = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            response = httpClient.execute(post);
            int statecode = response.getStatusLine().getStatusCode();
            if (statecode == 200) {
                HttpEntity httpentity = response.getEntity();
                if (httpentity != null) {
                    // 服务器返回的JSON字符串，建议要当做日志记录起来
                    result = EntityUtils.toString(httpentity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                post.abort();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;

    }

    // 后厨小票打印
    public String printOrder(List<ItemS> itemsList, TradeAccountConsumptionFlow tradeAccountConsumptionFlow, SystemPrinter systemPrinter) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DecimalFormat df = new DecimalFormat("0000");
        int b1 = 14, b2 = 6, b3 = 4, b4 = 6;
        String orderInfo = "<CB>" + systemProjectService.findByCode(PROJECT_CODE).getName() + "</CB>";
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<CB>序号:" + df.format(printSerialNumber.getAndIncrement()) + "</CB><BR>";
        orderInfo += "<CB>取餐码:" + tradeAccountConsumptionFlow.getTableNo() + "</CB>";
        orderInfo += "<QR>" + tradeAccountConsumptionFlow.getFlowNo() + "</QR><BR>";
        orderInfo += "<C>" + tradeAccountConsumptionFlow.getFlowNo() + "</C><BR>";
        orderInfo += "下单时间:" + format.format(tradeAccountConsumptionFlow.getCreateTime()) + "<BR>";
        orderInfo += "打印时间:" + format.format(LocalDateTime.now()) + "<BR>";
        orderInfo += "名称          数量      金额<BR>";
        orderInfo += "--------------------------------<BR>";
        String itemInfo = "";
        String remark = "";
        int nameLength = 0;
        for (ItemS items : itemsList) {
            try {
                nameLength = items.getItem().getBytes("GBK").length;
                if (nameLength > 12) {
                    itemInfo += "<L>" + items.getItem().substring(0, 6) + "</L>" + "<BR>";
                    nameLength -= 12;
                    itemInfo += "<L>" + String.format("%-" + (28 - nameLength) / 2 + "s", items.getItem().substring(6)) + "</L>";
                } else {
                    itemInfo = "<L>" + String.format("%-" + (28 - nameLength) / 2 + "s", items.getItem()) + "</L>";
                }
                itemInfo += String.format("%-8s", "X " + items.getCount())
                        + String.format("%6s", items.getCount() * items.getPrice());
                orderInfo += itemInfo + "<BR>";
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            if (StringUtils.hasText(items.getRemark())) {
                remark += items.getItem() + ":" + items.getRemark() + "<BR>";
            }
        }
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<CB>合计：   " + (tradeAccountConsumptionFlow.getDiscountAmount() + tradeAccountConsumptionFlow.getActualAmount()) + "</CB><BR>";
        orderInfo += "<CB>优惠：   " + tradeAccountConsumptionFlow.getDiscountAmount() + "</CB><BR>";
        orderInfo += "<CB>实付：   " + tradeAccountConsumptionFlow.getActualAmount() + "</CB>";
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<CB>  备餐信息 </CB><BR>";
        if (StringUtils.hasText(remark)) {
            orderInfo += "备注:<BR>" + remark + "<BR>";
        }
        orderInfo += "<BR><BR><BR><BR><BR><CUT>";
        String print = print(orderInfo, systemPrinter.getSn());
        return print;
    }

    /**
     * 储值小票打印
     *
     * @param tradeAccountStoreFlow
     * @param cardInfo
     * @param systemPrinter
     */
    public void printStoreOrder(TradeAccountStoreFlow tradeAccountStoreFlow, CardInfo cardInfo, SystemPrinter systemPrinter) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String orderInfo = "<C>储值小票</C><BR>";
        orderInfo += "--------------------------------<BR>";
        orderInfo += "姓名:" + cardInfo.getCustomer().getName() + "<BR>";
        orderInfo += "日期:" + format.format(LocalDateTime.now()) + "<BR>";
        orderInfo += "序号:" + tradeAccountStoreFlow.getFlowNo() + "<BR>";
        orderInfo += "充值前余额:" + tradeAccountStoreFlow.getBeforeAmount() + "<BR>";
        orderInfo += "充值金额:" + tradeAccountStoreFlow.getActualAmount() + "<BR>";
        orderInfo += "充值后余额:" + tradeAccountStoreFlow.getAfterAmount() + "<BR>";
        orderInfo += "操作员:" + tradeAccountStoreFlow.getCreatorName() + "<BR>";
        orderInfo += "充值前余额:" + tradeAccountStoreFlow.getBeforeAmount() + "<BR>";
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<C>储值成功</C><BR>";
        orderInfo += "<C>联系电话" + systemProjectService.findByCode(PROJECT_CODE).getLinkPhone() + "</C><BR>";
        orderInfo += "<BR><BR><BR><BR><BR><CUT>";
        print(orderInfo, systemPrinter.getSn());
    }

    public void cupStickersPrint(List<ItemS> itemsList, TradeAccountConsumptionFlow tradeAccountConsumptionFlow) {
        int no = 1;
        Map params = new HashMap<String, String>();
        for (ItemS items : itemsList) {
            for (int i = 0; i < items.getCount(); i++) {
                String reqTime = String.valueOf(Calendar.getInstance().getTimeInMillis());
                String securityCode = DigestUtils.md5Hex(memberCode + tablePrinterCode + reqTime + apiKey);
                params.put("reqTime", reqTime);
                params.put("securityCode", securityCode);
                params.put("memberCode", memberCode);
                params.put("templetID", templetID);
                params.put("deviceID", tradeAccountConsumptionFlow.getStickerPrinter().getSn());
                params.put("tData", tData(items, tradeAccountConsumptionFlow, no + ""));
                Request.sendPost("http://api.poscom.cn/apisc/templetPrint", params);
                no++;
            }
        }
    }

    // 查询打印机状态
    public String queryPrinterStatus(String sn) {

        // 通过POST请求，发送打印信息到服务器
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)// 读取超时
                .setConnectTimeout(30000)// 连接超时
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig).build();

        HttpPost post = new HttpPost(URL);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("user", USER));
        String STIME = String.valueOf(System.currentTimeMillis() / 1000);
        nvps.add(new BasicNameValuePair("stime", STIME));
        nvps.add(new BasicNameValuePair("sig", signature(USER, UKEY, STIME)));
        nvps.add(new BasicNameValuePair("apiname", "Open_queryPrinterStatus"));// 固定值,不需要修改
        nvps.add(new BasicNameValuePair("sn", sn));

        CloseableHttpResponse response = null;
        String result = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            response = httpClient.execute(post);
            int statecode = response.getStatusLine().getStatusCode();
            if (statecode == 200) {
                HttpEntity httpentity = response.getEntity();
                if (httpentity != null) {
                    // 服务器返回
                    result = EntityUtils.toString(httpentity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                post.abort();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;

    }


    private String tData(ItemS item, TradeAccountConsumptionFlow consumptionFlow, String no) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        Map<String, String> date = new HashMap<>();
        date.put("printeTime", format.format(LocalDateTime.now()));
        date.put("tableNo", consumptionFlow.getTableNo());
        date.put("courseName", item.getItem());
        date.put("total", consumptionFlow.getQuantity().intValue() + "");
        date.put("no", no);
        date.put("phone", systemProjectService.findByCode(PROJECT_CODE).getLinkPhone());
        date.put("prices", item.getPrice() + "");
        date.put("remark", item.getRemark());
        return JSONObject.toJSONString(date);
    }


}
